#include <pthread.h>
//#include <limits.h>
#include <semaphore.h>
#include <stdio.h>
#include <time.h>

sem_t semaphore_0;
sem_t semaphore_1;


sem_t created0_semaphore;
sem_t created1_semaphore;

volatile int count;
volatile int thread0_count = -1;
volatile int thread1_count = -1;

struct stack {
   char x[1024];
};

static struct stack stacks[2];

void* threadFn(void* ctx)
{
     int l = (int)ctx;
     sem_t* my_semaphore;
     sem_t* other_semaphore;
     sem_t* created;
     
     printf("thread %d started\n", l);
     if(l==0)
     {
        thread0_count = l;
        my_semaphore = &semaphore_0;
        other_semaphore = &semaphore_1;   
        created = &created0_semaphore;  
     }
     else
     {
        thread1_count = l;
        my_semaphore = &semaphore_1;
        other_semaphore = &semaphore_0;   
        created = &created1_semaphore;  
     }
     
     sem_post(created);
     
     while(1)
     {
        sem_wait(my_semaphore);
      //  printf("ping %d, %d\n", l, count);
        count--;
        sem_post(other_semaphore);
        if(count <= 0)
          break;
     }
     printf("finished\n");
}


int main(int argc, char* argv[])
{

   int count_start;

  pthread_attr_t stack_attr;
  
  pthread_t thread0;
  pthread_t thread1;
  time_t start;
  time_t end;
  
    if(argc != 2){
	printf("usage: test [count]\n");
	exit(0);
    }
    
  count_start = count = atoi(argv[1]);
  printf("Start. Count = %d\n", count);
    
  sem_init(&semaphore_0, 0, 0);
  sem_init(&semaphore_1, 0, 0);
  sem_init(&created0_semaphore, 0, 0);
  sem_init(&created1_semaphore, 0, 0);

  pthread_attr_init(&stack_attr);
#if 0  
  pthread_attr_setstack(&stack_attr, &stacks[0], sizeof(struct stack));
  pthread_create(&thread0, &stack_attr, threadFn, (void*)0 );
  pthread_attr_setstack(&stack_attr, &stacks[1], sizeof(struct stack));
  pthread_create(&thread1, &stack_attr, threadFn, (void*)1 );
#else
  pthread_create(&thread0, 0, threadFn, (void*)0 );
  pthread_create(&thread1, 0, threadFn, (void*)1 );
#endif
  sem_wait(&created0_semaphore);
  sem_wait(&created1_semaphore);
  printf("Threads created %d, %d\n", thread0_count, thread1_count);
  
  start = time(0);
  sem_post(&semaphore_0);
  
  pthread_join(thread0, 0);
  pthread_join(thread1, 0);
  end = time(0);
  
  
  printf("%d context switches in %d seconds. %f switches/sec\n", count_start, end-start, (float)count_start/(float)(end-start));
}
